1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, The Scope team
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name "Scope" nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 *
36 * $Id: SPanel.java,v 1.7 2002/09/13 17:04:40 ludovicc Exp $
37 */
38 package org.scopemvc.view.swing;
39
40
41 import java.awt.Component;
42 import java.awt.Container;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.scopemvc.controller.basic.BasicController;
46 import org.scopemvc.core.Control;
47 import org.scopemvc.core.PropertyView;
48 import org.scopemvc.core.Selector;
49 import org.scopemvc.core.View;
50 import org.scopemvc.view.util.ModelBindable;
51
52 /***
53 * <P>
54 *
55 * A JPanel implementation of View for use in Swing-based user interfaces.
56 * {@link org.scopemvc.controller.swing.SwingContext} uses the following methods
57 * from the {@link SwingView} base class that should be overridden in subclasses
58 * that can be shown as top-level views in a Window:
59 * <UL>
60 * <LI> {@link #getTitle}</LI>
61 * <LI> {@link #getDisplayMode}</LI>
62 * <LI> {@link #getCloseControl}</LI>
63 * <LI> {@link #isResizable}</LI>
64 * </UL>
65 * </P> <P>
66 *
67 * SPanel can be bound either to an entire model object, or to a property of a
68 * model. In either case it binds child components to the model it shows (either
69 * the entire model or a property of it, assumed to be a submodel). <B>Note:
70 * </B>See {@link SUnboundPanel} for an SPanel that doesn't bind to a model,
71 * isolating its contained views from the model-binding hierarchy. </P> <P>
72 *
73 * SPanel uses a {@link org.scopemvc.view.swing.SwingBoundModel SwingBoundModel}
74 * delegate. </P> <P>
75 *
76 * SPanel implements the CHANGE_MODEL_CONTROL_ID Control when the shown model
77 * object changes. This supports BasicController which needs to know when its
78 * current model changes. </P>
79 *
80 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
81 * @created 05 September 2002
82 * @version $Revision: 1.7 $ $Date: 2002/09/13 17:04:40 $
83 */
84 public class SPanel
85 extends SwingView
86 implements ModelBindable, Refreshable, PropertyView {
87
88 private static final Log LOG = LogFactory.getLog(SPanel.class);
89
90 // ------------------- Delegate to SwingBoundModel -------------------
91
92 /***
93 * Helper to manage model to view binding.
94 */
95 private SwingBoundModel boundModel = new SwingBoundModel(this);
96
97 // --------------------- shownModel -----------------------
98
99 /***
100 * The model object that the SPanel presents, which may be a property of the
101 * bound model if a Selector is specified.
102 */
103 private Object shownModel;
104
105
106 private static void populateSubComponents(Component inComponent, Object inModel) {
107 if (inComponent instanceof SwingView) {
108 if (LOG.isDebugEnabled()) {
109 LOG.debug("populateSubComponents: component: " + inComponent + ", subview count: " + ((SwingView) inComponent).getSubViewCount());
110 }
111 for (int i = ((SwingView) inComponent).getSubViewCount() - 1; i >= 0; --i) {
112 SwingSubView ssv = ((SwingView) inComponent).getSubView(i);
113 if (LOG.isDebugEnabled()) {
114 LOG.debug("populateSubComponents: subview: " + ssv);
115 }
116 ssv.setBoundModel(inModel);
117 }
118 }
119
120 if (!(inComponent instanceof Container)) {
121 return;
122 }
123
124 if (LOG.isDebugEnabled()) {
125 LOG.debug("populateSubComponents: component: " + inComponent + ", component count: " + ((Container) inComponent).getComponentCount());
126 }
127 for (int i = ((Container) inComponent).getComponentCount() - 1; i >= 0; --i) {
128 Component c = ((Container) inComponent).getComponent(i);
129 if (c instanceof View) {
130 ((View) c).setBoundModel(inModel);
131 } else {
132 populateSubComponents(c, inModel);
133 }
134 }
135 }
136
137
138 private static void refreshSubComponents(Component inComponent) {
139 if (inComponent instanceof SwingView) {
140 for (int i = ((SwingView) inComponent).getSubViewCount() - 1; i >= 0; --i) {
141 SwingSubView ssv = ((SwingView) inComponent).getSubView(i);
142 if (ssv instanceof Refreshable) {
143 ((Refreshable) ssv).refresh();
144 }
145 }
146 }
147
148 if (!(inComponent instanceof Container)) {
149 return;
150 }
151
152 for (int i = ((Container) inComponent).getComponentCount() - 1; i >= 0; --i) {
153 Component c = ((Container) inComponent).getComponent(i);
154 if (c instanceof Refreshable) {
155 ((Refreshable) c).refresh();
156 } else {
157 refreshSubComponents(c);
158 }
159 }
160 }
161
162
163 /***
164 * Gets the bound model
165 *
166 * @return The boundModel value
167 */
168 public final Object getBoundModel() {
169 return boundModel.getBoundModel();
170 }
171
172
173 /***
174 * Gets the selector
175 *
176 * @return The selector value
177 */
178 public final Selector getSelector() {
179 return boundModel.getSelector();
180 }
181
182
183 /***
184 * Makes no sense: can't change the property using an SPanel!
185 *
186 * @return The viewValue value
187 */
188 public final Object getViewValue() {
189 return getShownModel();
190 }
191
192
193 /***
194 * Get the model object that the SPanel presents, which may be a property of
195 * the bound model if a Selector is specified.
196 *
197 * @return The shownModel value
198 */
199 public final Object getShownModel() {
200 return shownModel;
201 }
202
203
204 /***
205 * Sets the selector
206 *
207 * @param inSelector The new selector value
208 */
209 public final void setSelector(Selector inSelector) {
210 boundModel.setSelector(inSelector);
211 }
212
213
214 /***
215 * Sets the selector string
216 *
217 * @param inSelectorString The new selectorString value
218 */
219 public final void setSelectorString(String inSelectorString) {
220 boundModel.setSelectorString(inSelectorString);
221 }
222
223
224 /***
225 * Sets the bound model
226 *
227 * @param inModel The new boundModel value
228 */
229 public void setBoundModel(Object inModel) {
230 boundModel.setBoundModel(inModel);
231 }
232
233
234 // --------------------- Implement ModelBindable ----------------------
235
236 /***
237 * Ignores inReadOnly.
238 *
239 * @param inValue TODO: Describe the Parameter
240 * @param inReadOnly TODO: Describe the Parameter
241 */
242 public void updateFromProperty(Object inValue, boolean inReadOnly) {
243 if (LOG.isDebugEnabled()) {
244 LOG.debug("updateFromProperty: " + inValue + ", " + inReadOnly);
245 }
246
247 setShownModel(inValue);
248 }
249
250
251 /***
252 * Makes no sense.
253 *
254 * @param inException TODO: Describe the Parameter
255 */
256 public void validationFailed(Exception inException) {
257 // noop
258 }
259
260
261 /***
262 * Makes no sense.
263 */
264 public void validationSuccess() {
265 // noop
266 }
267
268
269 // ------------------ Refreshable -------------------------
270
271 /***
272 * TODO: document the method
273 */
274 public void refresh() {
275 // Get the model's state
276 Object propertyValue = boundModel.getPropertyValue();
277 boolean propertyReadOnly = boundModel.getPropertyReadOnly();
278
279 // If no change in shown model then just refresh children
280 // ... else update this and children will be updated automatically
281 if (getShownModel() == propertyValue) {
282 refreshSubComponents(this);
283 } else {
284 updateFromProperty(propertyValue, propertyReadOnly);
285 }
286 }
287
288
289 /***
290 * Called internally from updateFromProperty(). Issues a
291 * CHANGE_MODEL_CONTROL_ID Control to notify parent Controller of the
292 * change.
293 *
294 * @param inModel The new shownModel value
295 */
296 private void setShownModel(Object inModel) {
297
298 if (shownModel == inModel) {
299 return;
300 }
301
302 shownModel = inModel;
303
304 // Issue the BasicController.CHANGE_MODEL_CONTROL_ID
305 // Only valid for this View, so don't use the usual delegation to
306 // ... the nearest View that has a Controller
307 if (getController() != null) {
308 getController().handleControl(new Control(BasicController.CHANGE_MODEL_CONTROL_ID, shownModel));
309 }
310
311 // Now pass on the new shown model object to all sub-Views
312 if (LOG.isDebugEnabled()) {
313 LOG.debug("updateFromModel: updating child Views with model " + inModel);
314 }
315 populateSubComponents(this, inModel);
316 }
317 }
318
This page was automatically generated by Maven